<!-- @format -->

<template>
  <div class="echarts-container">
    <div class="echarts-map" ref="echartsRef"></div>
  </div>
</template>

<script setup lang="ts">
  import { ref, onMounted, onUnmounted, defineProps } from 'vue'
  import * as echarts from 'echarts'

  // 属性定义 start
  interface Props {
    date?: string
  }

  const props = defineProps<Props>()
  // 属性定义 end

  // 图表实例和DOM引用 start
  const echartsRef = ref<HTMLElement | null>(null)
  let theChartInstance: echarts.ECharts | null = null
  // 图表实例和DOM引用 end

  // 数据定义 start
  interface DataPoint {
    value: [number, number, number] // x坐标, y坐标, 浓度值
    itemStyle?: {
      color: string
    }
    symbolSize?: number
  }

  // 模拟数据点，实际应用中可以通过props传入
  const theDataPoints: DataPoint[] = []

  // 根据浓度值获取颜色
  const onGetColorByValue = (value: number): string => {
    if (value >= 80) return '#006400' // 深绿色
    if (value >= 50) return '#00FF00' // 亮绿色
    if (value >= 30) return '#90EE90' // 淡绿色
    if (value >= 10) return '#FFFFE0' // 淡黄色
    return '#FFFFFF' // 白色
  }

  // 根据浓度值获取点大小
  const onGetSymbolSize = (value: number): number => {
    if (value >= 80) return 12
    if (value >= 50) return 10
    if (value >= 30) return 8
    if (value >= 10) return 6
    return 4
  }

  // 生成模拟数据 - 更接近图片中的地形分布
  const onGenerateData = () => {
    // 清空数据
    theDataPoints.length = 0

    // 创建地形轮廓数据 - 模拟不规则地形
    const theContourLines: number[][][] = []

    // 创建一个更不规则的地形基础
    const theBasePoints: { x: number; y: number }[] = [
      { x: 20, y: 20 },
      { x: 30, y: 15 },
      { x: 50, y: 10 },
      { x: 70, y: 15 },
      { x: 85, y: 25 },
      { x: 90, y: 40 },
      { x: 85, y: 60 },
      { x: 75, y: 75 },
      { x: 60, y: 85 },
      { x: 40, y: 80 },
      { x: 25, y: 70 },
      { x: 15, y: 55 },
      { x: 10, y: 40 },
      { x: 15, y: 30 },
    ]

    // 生成多层等高线
    for (let i = 0; i < 15; i++) {
      const contourLine: number[][] = []
      const scaleFactor = 1 - i * 0.05
      const centerX = 50
      const centerY = 50

      // 基于基础点生成等高线
      for (let j = 0; j < theBasePoints.length; j++) {
        const point = theBasePoints[j]
        // 向中心缩放，形成等高线效果
        const x = centerX + (point.x - centerX) * scaleFactor
        const y = centerY + (point.y - centerY) * scaleFactor
        // 添加随机扰动使轮廓更自然
        const distortionX = (Math.random() - 0.5) * 3 * (1 - scaleFactor)
        const distortionY = (Math.random() - 0.5) * 3 * (1 - scaleFactor)
        contourLine.push([x + distortionX, y + distortionY])
      }

      // 闭合曲线
      if (contourLine.length > 0) {
        contourLine.push([contourLine[0][0], contourLine[0][1]])
      }

      theContourLines.push(contourLine)
    }

    // 生成散点数据 - 模拟浓度分布
    // 创建几个高浓度区域 - 更接近图片中的分布
    const highDensityAreas = [
      { x: 30, y: 60, radius: 12, intensity: 10 }, // 左侧中部
      { x: 70, y: 40, radius: 15, intensity: 12 }, // 右侧上部
      { x: 50, y: 80, radius: 10, intensity: 8 }, // 中下部
      { x: 25, y: 30, radius: 8, intensity: 7 }, // 左上角
      { x: 80, y: 70, radius: 10, intensity: 9 }, // 右下角
      { x: 60, y: 25, radius: 7, intensity: 6 }, // 右上部
    ]

    // 添加一些线性分布的高浓度带
    const theLinearBands = [
      { startX: 20, startY: 70, endX: 40, endY: 90, width: 10, intensity: 9 },
      { startX: 60, startY: 30, endX: 80, endY: 60, width: 12, intensity: 10 },
    ]

    // 生成更密集的点
    for (let x = 10; x <= 90; x += 3) {
      for (let y = 10; y <= 90; y += 3) {
        // 基础浓度值 - 根据地形高度（到中心的距离）
        const distToCenter = Math.sqrt(
          Math.pow(x - 50, 2) + Math.pow(y - 50, 2),
        )
        let value = Math.max(1, 10 - distToCenter / 10)

        // 根据到高浓度区域的距离增加浓度值
        for (const area of highDensityAreas) {
          const distance = Math.sqrt(
            Math.pow(x - area.x, 2) + Math.pow(y - area.y, 2),
          )
          if (distance < area.radius) {
            // 距离越近，浓度越高
            value += ((area.radius - distance) * area.intensity) / 2
          }
        }

        // 添加线性带状高浓度区域
        for (const band of theLinearBands) {
          // 计算点到线段的距离
          const A = band.endY - band.startY
          const B = band.startX - band.endX
          const C = band.endX * band.startY - band.startX * band.endY
          const distance =
            Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B)

          // 检查点是否在线段范围内
          const dotProduct =
            (x - band.startX) * (band.endX - band.startX) +
            (y - band.startY) * (band.endY - band.startY)
          const squaredLength =
            Math.pow(band.endX - band.startX, 2) +
            Math.pow(band.endY - band.startY, 2)

          if (
            dotProduct >= 0 &&
            dotProduct <= squaredLength &&
            distance < band.width
          ) {
            // 距离线越近，浓度越高
            value += ((band.width - distance) * band.intensity) / 3
          }
        }

        // 添加一些随机扰动
        value += (Math.random() - 0.3) * 8

        // 限制最大值
        value = Math.min(value, 100)

        // 只添加浓度大于1的点
        if (value > 1) {
          theDataPoints.push({
            value: [x, y, value],
            itemStyle: {
              color: onGetColorByValue(value),
            },
            symbolSize: onGetSymbolSize(value),
          })
        }
      }
    }

    // 添加一些随机的高浓度点
    for (let i = 0; i < 15; i++) {
      const x = 20 + Math.random() * 60
      const y = 20 + Math.random() * 60
      const value = 70 + Math.random() * 30

      theDataPoints.push({
        value: [x, y, value],
        itemStyle: {
          color: onGetColorByValue(value),
        },
        symbolSize: onGetSymbolSize(value),
      })
    }
  }
  // 数据定义 end

  // 图表初始化和配置 start
  const onInitChart = () => {
    if (!echartsRef.value) return

    // 生成数据
    onGenerateData()

    // 初始化echarts实例
    theChartInstance = echarts.init(echartsRef.value)

    // 创建等高线数据
    const theContourData: any[] = []
    for (let i = 0; i < 15; i++) {
      // 创建不同高度的等高线
      const scaleFactor = 1 - i * 0.05
      const centerX = 50
      const centerY = 50

      // 基础点
      const theBasePoints: [number, number][] = [
        [20, 20],
        [30, 15],
        [50, 10],
        [70, 15],
        [85, 25],
        [90, 40],
        [85, 60],
        [75, 75],
        [60, 85],
        [40, 80],
        [25, 70],
        [15, 55],
        [10, 40],
        [15, 30],
      ]

      // 生成等高线点
      const contourPoints: [number, number][] = []
      for (const [x, y] of theBasePoints) {
        // 向中心缩放，形成等高线效果
        const newX = centerX + (x - centerX) * scaleFactor
        const newY = centerY + (y - centerY) * scaleFactor
        // 添加随机扰动使轮廓更自然
        const distortionX = (Math.random() - 0.5) * 2 * (1 - scaleFactor)
        const distortionY = (Math.random() - 0.5) * 2 * (1 - scaleFactor)
        contourPoints.push([newX + distortionX, newY + distortionY])
      }

      // 闭合曲线
      if (contourPoints.length > 0) {
        contourPoints.push([contourPoints[0][0], contourPoints[0][1]])
      }

      // 添加到等高线数据
      theContourData.push({
        type: 'line',
        coordinateSystem: 'cartesian2d',
        data: contourPoints,
        symbol: 'none',
        lineStyle: {
          color: '#333',
          width: 1,
          opacity: 0.3 + i * 0.03,
        },
        emphasis: {
          lineStyle: {
            opacity: 0.6 + i * 0.03,
          },
        },
      })
    }

    // 添加一些地形特征线
    const theTerrainFeatures = [
      // 山脊线
      {
        points: [
          [30, 20],
          [45, 35],
          [60, 30],
          [75, 45],
        ],
        color: '#ff0000',
        width: 1.5,
        opacity: 0.5,
      },
      // 山谷线
      {
        points: [
          [25, 50],
          [40, 60],
          [60, 55],
          [75, 65],
        ],
        color: '#ff0000',
        width: 1.5,
        opacity: 0.5,
      },
      // 河流
      {
        points: [
          [20, 70],
          [35, 75],
          [50, 65],
          [65, 75],
          [80, 65],
          [160, 125],
        ],
        color: '#ff0000',
        width: 2,
        opacity: 0.6,
      },
    ]

    // 添加地形特征线到等高线数据
    for (const feature of theTerrainFeatures) {
      theContourData.push({
        type: 'line',
        coordinateSystem: 'cartesian2d',
        data: feature.points,
        symbol: 'none',
        lineStyle: {
          color: feature.color,
          width: feature.width,
          opacity: feature.opacity,
          type: feature.points[0][0] === 20 ? 'dashed' : 'solid', // 河流使用虚线
        },
      })
    }

    // 配置项
    const theOption = {
      backgroundColor: '#f8f8f8',
      title: {
        text: '地形浓度散点图',
        subtext: props.date || '2025/5/1',
        left: 'right',
        top: 10,
        textStyle: {
          fontSize: 16,
          fontWeight: 'normal',
        },
        subtextStyle: {
          fontSize: 12,
        },
      },
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          if (params.value && params.value.length > 2) {
            const value = params.value
            return `坐标: (${value[0].toFixed(0)}, ${value[1].toFixed(0)})<br/>浓度值: ${value[2].toFixed(1)}`
          }
          return ''
        },
      },
      grid: {
        left: 5,
        right: 15,
        top: 50,
        bottom: 80,
        containLabel: true,
      },
      xAxis: {
        type: 'value',
        scale: true,
        min: 0,
        max: 100,
        axisLine: {
          show: true,
          lineStyle: { opacity: 0.3 },
        },
        axisTick: { show: false },
        axisLabel: { show: false },
        splitLine: {
          show: true,
          lineStyle: {
            type: 'dashed',
            color: '#ccc',
            opacity: 0.2,
          },
        },
      },
      yAxis: {
        type: 'value',
        scale: true,
        min: 0,
        max: 100,
        axisLine: {
          show: true,
          lineStyle: { opacity: 0.3 },
        },
        axisTick: { show: false },
        axisLabel: { show: false },
        splitLine: {
          show: true,
          lineStyle: {
            type: 'dashed',
            color: '#ccc',
            opacity: 0.2,
          },
        },
      },
      series: [
        // 等高线
        ...theContourData,
        // 散点图 - 主数据
        {
          type: 'scatter',
          data: theDataPoints,
          emphasis: {
            focus: 'series',
            itemStyle: {
              shadowBlur: 10,
              shadowColor: 'rgba(0, 0, 0, 0.5)',
            },
          },
        },
        // 特效散点 - 高浓度点
        {
          type: 'effectScatter',
          symbolSize: 15,
          data: theDataPoints
            .filter((point) => point.value[2] >= 80)
            .map((point) => point.value),
          showEffectOn: 'render',
          rippleEffect: {
            brushType: 'stroke',
            period: 4,
            scale: 3,
          },
          hoverAnimation: true,
          itemStyle: {
            color: '#006400',
            shadowBlur: 10,
            shadowColor: '#333',
          },
          zlevel: 1,
        },
      ],
      visualMap: {
        type: 'piecewise',
        left: 'left',
        bottom: 10,
        orient: 'horizontal',
        pieces: [
          { min: 80, max: 1000, label: '>= 80, <1000', color: '#006400' },
          { min: 50, max: 80, label: '>= 50, < 80', color: '#00FF00' },
          { min: 30, max: 50, label: '>= 30, < 50', color: '#90EE90' },
          { min: 10, max: 30, label: '>= 10, < 30', color: '#FFFFE0' },
          { min: 1, max: 10, label: '>= 1, < 10', color: '#FFFFFF' },
        ],
        textStyle: {
          color: '#333',
        },
      },
    }

    // 设置配置项
    theChartInstance.setOption(theOption)
  }
  // 图表初始化和配置 end

  // 窗口大小变化处理 start
  const onResizeHandler = () => {
    theChartInstance?.resize()
  }
  // 窗口大小变化处理 end

  // 生命周期钩子 start
  onMounted(() => {
    onInitChart()
    window.addEventListener('resize', onResizeHandler)
  })

  onUnmounted(() => {
    window.removeEventListener('resize', onResizeHandler)
    theChartInstance?.dispose()
    theChartInstance = null
  })
  // 生命周期钩子 end
</script>

<style lang="scss" scoped>
  .echarts-container {
    width: 100%;
    height: 100%;

    .echarts-map {
      width: 100%;
      height: 500px;
    }
  }
</style>
